﻿using Microsoft.CSharp;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Web.Script.Serialization;

public class DynamicLoader
{
    /// <summary>
    ///  传入源代码 获取编译后的程序集
    /// </summary>
    /// <param name="sourceCode">源代码</param>
    /// <returns>程序集</returns>
    public static Assembly GetAssembly(string sourceCode)
    {
        CSharpCodeProvider codeProvider = new CSharpCodeProvider();
        CompilerParameters parameters = new CompilerParameters();

        parameters.ReferencedAssemblies.Add("mscorlib.dll");
        parameters.ReferencedAssemblies.Add("System.dll");
        parameters.ReferencedAssemblies.Add("System.Data.dll");
        parameters.ReferencedAssemblies.Add("System.Data.SQLite.dll");
        parameters.ReferencedAssemblies.Add("System.Xml.dll");
        parameters.ReferencedAssemblies.Add("System.Web.Extensions.dll");
        parameters.ReferencedAssemblies.Add("System.Data.DataSetExtensions.dll");

        CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, sourceCode);

        if (results.Errors.HasErrors)
        {
            Console.WriteLine("编译错误:----------------------");
            foreach (CompilerError error in results.Errors)
            {
                Console.WriteLine(error.ErrorText);
            }
            return null;
        }
        Assembly assembly = results.CompiledAssembly;
        return assembly;
    }

    /// <summary>
    /// 检查编译是否报错
    /// </summary>
    /// <param name="code">源代码</param>
    /// <returns></returns>
    public static string CheckAssembly(string code)
    {
        StringBuilder stringBuilder = new StringBuilder("");
        try
        {
            CSharpCodeProvider codeProvider = new CSharpCodeProvider();
            CompilerParameters parameters = new CompilerParameters();

            parameters.GenerateInMemory = true;
            parameters.ReferencedAssemblies.Add("mscorlib.dll");
            parameters.ReferencedAssemblies.Add("System.dll");
            parameters.ReferencedAssemblies.Add("System.Data.dll");
            parameters.ReferencedAssemblies.Add("System.Data.SQLite.dll");
            parameters.ReferencedAssemblies.Add("System.Xml.dll");
            parameters.ReferencedAssemblies.Add("System.Web.Extensions.dll");
            parameters.ReferencedAssemblies.Add("System.Data.DataSetExtensions.dll");

            CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters, code);

            if (results.Errors.HasErrors)
            {
                Console.WriteLine("编译错误:");
                foreach (CompilerError error in results.Errors)
                {
                    stringBuilder.Append(error.ErrorText + "\n");
                }
            }
        }
        catch (Exception ex)
        {
            stringBuilder.Append(ex.Message);
        }
        return stringBuilder.ToString();
    }

    /// <summary>
    /// 根据源代码获取变量的值
    /// </summary>
    /// <param name="sourceCode">源代码</param>
    /// <param name="param">变量值</param>
    /// <returns></returns>
    public static object getParam(string sourceCode, string param)
    {
        Assembly assembly = GetAssembly(sourceCode);
        Type myClassType = assembly.GetType("ClassName");
        object myClassInstance = Activator.CreateInstance(myClassType);
        FieldInfo myValueField = myClassType.GetField(param);
        return myValueField.GetValue(myClassInstance);
    }

    /// <summary>
    /// 根据源代码获取方法列表和描述信息
    /// </summary>
    /// <param name="code"></param>
    /// <returns></returns>
    public static List<string> getMethodInfo(string code)
    {
        List<string> result = new List<string>();
        try
        {
            Assembly assembly = GetAssembly(code);
            Type myClassType = assembly.GetType("ClassName");
            object myClassInstance = Activator.CreateInstance(myClassType);
            MethodInfo[] ssss = myClassType.GetMethods();
            for (int i = 0; i < ssss.Length; i++)
            {
                var md = ssss[i];
                string methodName = md.Name;
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.Append("方法名:" + methodName);
                if (methodName.Contains("MethodName"))
                {
                    ParameterInfo[] paramInfos = md.GetParameters();
                    int parameterCount = paramInfos.Length;
                    stringBuilder.Append(" 参数个数:" + parameterCount);
                    for (int j = 0; j < parameterCount; j++)
                    {
                        string type = paramInfos[j].ParameterType.Name;
                        int pos = paramInfos[j].Position;
                        string paramname = paramInfos[j].Name;
                        stringBuilder.Append(" 位置:" + pos + "-" + type + "-" + paramname);
                    }
                    stringBuilder.Append("\n");
                    result.Add(stringBuilder.ToString());
                }
            }
        }
        catch (Exception ex)
        {
            string result1 = "调用报错:" + ex.Message;
            result.Add(result1);
        }
        return result;
    }

    /// <summary>
    /// 获取调用方法出错原因
    /// </summary>
    /// <param name="code">源代码</param>
    /// <param name="type">参数类型</param>
    /// <param name="data">参数值</param>
    /// <returns></returns>
    public static string CheckMethod(string code, Type[] type, object[] data)
    {
        string result = "";
        try
        {
            Assembly assembly = GetAssembly(code);
            Type myClassType = assembly.GetType("ClassName");
            object myClassInstance = Activator.CreateInstance(myClassType);
            MethodInfo method = myClassType.GetMethod("MethodName", type == null ? new Type[] { } : type);
            method.Invoke(myClassInstance, data);
        }
        catch (Exception ex)
        {
            result = "调用报错:" + ex.Message;
        }
        return result;
    }

    /// <summary>
    /// 动态调用某方法获取返回值
    /// </summary>
    /// <param name="code">源代码</param>
    /// <param name="type">参数类型</param>
    /// <param name="data">参数值</param>
    /// <returns></returns>
    public static object getMethod(string code, Type[] type, object[] data)
    {
        Type[] types = new Type[] {};
        if (data != null){}
        Assembly assembly = GetAssembly(code);
        Type myClassType = assembly.GetType("ClassName");
        object myClassInstance = Activator.CreateInstance(myClassType);
        MethodInfo sayHelloMethod = myClassType.GetMethod("MethodName", type == null ? types : type);
        object result = sayHelloMethod.Invoke(myClassInstance, data);
        return result;
    }

    /// <summary>
    /// 根据输出的类解析医保返回值
    /// </summary>
    /// <param name="code">输出值实体类</param>
    /// <param name="output">输出json字符串</param>
    /// <returns></returns>
    public static dynamic getOutput(string code, string output)
    {
        Assembly assembly = GetAssembly(code);
        Type dynamicType = assembly.GetType("Output");
        //dynamic obj = JsonConvert.DeserializeObject(output, dynamicType);
        // 直接转对象
        //dynamic obj1 = JsonConvert.DeserializeObject(output) as dynamic;
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        serializer.MaxJsonLength = int.MaxValue;
        dynamic obj = serializer.Deserialize(output, dynamicType);
        return obj;
    }
}